home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus 2000 #5 / Amiga Plus CD - 2000 - No. 5.iso / Tools / Dev / FPSE_src / joypad.c < prev    next >
C/C++ Source or Header  |  2000-01-01  |  7KB  |  279 lines

  1. /*
  2.     Gamepad & memory card emulation
  3.     ===============================
  4.  
  5.     Written by LDChen
  6. */
  7.  
  8. #include "fpse.h"
  9.  
  10. #define ACKPAD   sio->Delta |= DSR;
  11. #define NACKPAD  
  12. // sio->Status &= ~DSR; sio->Delta |= DSR;
  13.  
  14. #define B13         0x2000
  15. #define READ_CARD   0x80
  16.  
  17. #define KPAD    1
  18. #define KMEM    2
  19.  
  20. #ifdef MSB_FIRST
  21. #define L0      3
  22. #define L1      2
  23. #else
  24. #define L0      0
  25. #define L1      1
  26. #endif
  27.  
  28. // This struct should be allocate in SIO_Type in the future...
  29. typedef struct {
  30.     int    Type;
  31.     int    Ptr;
  32. /* Gamepad fields */
  33.     int    PadEnd;
  34.     void (*Joy_PollBack)(void);
  35.     void (*Joy_Vibrate)(int);
  36.     char   Buf[16];
  37. /* Memory card fields */
  38.     char   MemBuf[256];
  39.     union {
  40.         UINT8  l[4];
  41.         UINT32 hl;
  42.     } Addr;
  43.     int    EndFlg,Crc;
  44.     char  *CardName;
  45.     char   MemoryCard[128*1024];
  46. } pad_type;
  47.  
  48. static pad_type *flx=NULL;
  49. static pad_type  pad[2];
  50. static int       nflx=0;
  51. static char      cd1[] = {"slot1"};
  52. static char      cd2[] = {"slot2"};
  53. static char      memcdpath[] = { "memcards\\" };
  54.  
  55. static int MC_Event();
  56. static int MC_VSync();
  57.  
  58. int PAD_Init(SIO_Type *sio)
  59. {
  60.     int  f,x;
  61.     char buf[80];
  62.  
  63. // Prepare the struct
  64.     memset(pad,0,sizeof(pad));
  65.  
  66.     strcpy(buf,memcdpath);
  67.     if (FPSEIni.Mcd1Name != NULL) strcat(buf,FPSEIni.Mcd1Name);
  68.                              else strcat(buf,cd1);
  69.     pad[0].CardName = strdup(buf);
  70.  
  71.     strcpy(buf,memcdpath);
  72.     if (FPSEIni.Mcd2Name != NULL) strcat(buf,FPSEIni.Mcd2Name);
  73.                              else strcat(buf,cd2);
  74.     pad[1].CardName = strdup(buf);
  75.  
  76. // GamePad header
  77.     pad[0].Joy_PollBack = JOY0_Poll;
  78.     pad[0].Joy_Vibrate  = JOY0_Vibrate;
  79.     pad[0].PadEnd       = JOY0_InitHeader(pad[0].Buf);
  80.     pad[1].Joy_PollBack = JOY1_Poll;
  81.     pad[1].Joy_Vibrate  = JOY1_Vibrate;
  82.     pad[1].PadEnd       = JOY1_InitHeader(pad[1].Buf);
  83.  
  84.     for (x=0;x<2;x++)
  85.     {
  86. // Memory card header
  87.         pad[x].MemBuf[2] = 0x5A;
  88.         pad[x].MemBuf[3] = 0x5D;
  89.  
  90. // Load memory card
  91.         f = open(pad[x].CardName, O_RDONLY|O_BINARY);
  92.         if (f!=-1)
  93.         {
  94.             read(f,pad[x].MemoryCard,128*1024);
  95.             close(f);
  96.         }
  97.     }
  98.  
  99. // Handlers
  100.     EventCallBack[INT_SIO0] = MC_Event;
  101.     VSyncCallBack[INT_SIO0] = MC_VSync;
  102.  
  103. // Times to wait before irq
  104.     sio->IrqSrc   = SIO_IRQ_ASYNC;
  105.     sio->IrqFlags = 0x00000003;
  106.  
  107.     return FPSE_OK;
  108. }
  109.  
  110. void PAD_Close(SIO_Type *sio)
  111. {
  112.     free(pad[0].CardName);
  113.     free(pad[1].CardName);
  114.     JOY0_Close();
  115.     JOY1_Close();
  116. }
  117.  
  118. void PAD_WriteData(SIO_Type *sio)
  119. {
  120.  UINT8 *buf = sio->TxBuf;
  121.  int    v;
  122.  UINT8  crc;
  123.  
  124.  if (flx == NULL) return;
  125.  
  126.  if (flx->Ptr == 0)
  127.     {
  128.         switch (*buf) {
  129.         case 0x01:
  130.             flx->Type = KPAD; flx->Ptr = 1;
  131.             sio->IrqSrc   = SIO_IRQ_ASYNC;
  132.             sio->IrqFlags = 0x00000003;
  133.             break;
  134.         case 0x81:
  135.             flx->Type = KMEM; flx->Ptr = 1;
  136.             sio->IrqSrc   = SIO_IRQ_VSYNC;
  137.             if (compile)
  138.                 sio->IrqFlags = 0x00000001;
  139.             else
  140.                 sio->IrqFlags = 0x00000002;
  141.             break;
  142.         default: break;
  143.         }
  144.         ACKPAD
  145.         sio_async(sio,flx->Buf,1);
  146.         NACKPAD
  147.         return;
  148.     }
  149.  
  150.  if (flx->Type == KPAD)
  151.     {
  152.         if (flx->Ptr == 1)
  153.             {
  154.                 if ((*buf & 0x40) != 0x40)
  155.                     {
  156.                         ACKPAD
  157.                         sio_async(sio,flx->Buf,1);
  158.                         NACKPAD
  159.                         flx->Ptr = 0;
  160.                         return;
  161.                     }
  162.                 else flx->Joy_PollBack();
  163.  
  164.             } else flx->Joy_Vibrate(*buf);
  165.         if (flx->Ptr < flx->PadEnd-1) ACKPAD
  166.         sio_async(sio,flx->Buf + flx->Ptr,1);
  167.         NACKPAD
  168.         if (++flx->Ptr >= flx->PadEnd) flx->Ptr = 0;
  169.         return;
  170.     }
  171.  
  172.  if ((flx->Type & 0x7F) == KMEM)
  173.     {
  174.         if (flx->Ptr == 1)
  175.             {
  176.                 switch (*buf) {
  177.                 case 'R':
  178.                     flx->Type |= READ_CARD;
  179.                     flx->EndFlg = 140;
  180.                     break;
  181.                 case 'W':
  182.                     flx->EndFlg = 138;
  183.                     break;
  184.                 default:
  185.                     flx->Ptr = 0;
  186.                     return;
  187.                 }
  188.             }
  189.         if (flx->Type & READ_CARD)
  190.             {
  191.                 switch (flx->Ptr) {
  192.                 case 4:
  193.                     flx->Addr.l[L1] = *buf;
  194.                     flx->MemBuf[5] = *buf;
  195.                     flx->MemBuf[6] = 0x5C;
  196.                     flx->MemBuf[7] = 0x5D;
  197.                     flx->MemBuf[8] = *buf;
  198.                     break;
  199.                 case 5:
  200.                     flx->Addr.l[L0] = *buf;
  201.                     flx->MemBuf[9] = *buf;
  202.                     memcpy(flx->MemBuf+10,
  203.                            flx->MemoryCard+flx->Addr.hl*128,
  204.                            128);
  205.                     crc = 0; // pad[flx].Addr.l[0] ^ pad[flx].Addr.l[1];
  206.                     for (v=8;v<128+10;v++)
  207.                         crc ^= flx->MemBuf[v];
  208.                     flx->MemBuf[v] = crc;
  209.                     flx->MemBuf[v+1] = 0x47;
  210.                     break;
  211.                 }
  212.             }
  213.         else {
  214.                 switch (flx->Ptr) {
  215.                 case 4:
  216.                     flx->Addr.l[L1] = *buf;
  217.                     flx->MemBuf[135] = 0x5C;
  218.                     flx->MemBuf[136] = 0x5D;
  219.                     flx->MemBuf[137] = 0x47;
  220.                     break;
  221.                 case 5:
  222.                     flx->Addr.l[L0] = *buf;
  223.                     flx->Crc = 0; // flx->Addr.l[0] ^ flx->Addr.l[1];
  224.                     break;
  225.                 case 134:
  226.                     printf("caculated crc=%02x\n",flx->Crc);
  227.                     if (*buf != flx->Crc)
  228.                     {
  229.                         flx->MemBuf[137] = 0x4E;
  230.                         break;
  231.                     }
  232.                     memcpy(flx->MemoryCard+flx->Addr.hl*128,
  233.                            flx->MemBuf+7,128);
  234.                 }
  235.                 if (flx->Ptr > 3 &&
  236.                     flx->Ptr < 134)
  237.                 {
  238.                     flx->MemBuf[flx->Ptr+1] = *buf;
  239.                     flx->Crc ^= *buf;
  240.                 }
  241.             }
  242.         if (flx->Ptr < flx->EndFlg) ACKPAD
  243.         sio_async(sio,flx->MemBuf + flx->Ptr,1);
  244.         NACKPAD
  245.         if (++flx->Ptr >= flx->EndFlg) flx->Ptr = 0;
  246. //        pad[flx].ptr = 0;
  247. //        return;
  248.     }
  249. }
  250.  
  251. void PAD_UpdateStatus(SIO_Type *sio)
  252. {
  253.  if (!(sio->Ctrl.Control16 & 2)) {
  254.     pad[0].Ptr = pad[1].Ptr = 0;
  255.     VSync_Register &= ~(1<<INT_SIO0);
  256.     Event_Register &= ~(1<<INT_SIO0);
  257.     
  258.     flx = NULL;
  259.     return;
  260.  }
  261.  
  262.  if (sio->Ctrl.Control16 & B13) nflx = 1;
  263.                            else nflx = 0;
  264.  flx = pad + nflx;
  265. }
  266.  
  267. static int MC_Event()
  268. {
  269.     VSync_Register &= ~(1<<INT_SIO0);
  270.  
  271.     return 1;
  272. }
  273.  
  274. static int MC_VSync()
  275. {
  276.     Event_Register &= ~(1<<INT_SIO0);
  277.  
  278.     return 1;
  279. }